#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/evp.h>
#include <openssl/sha.h>

int main(int argc, char* argv[])
{
    if(argc != 3)
    {
        perror("参数传输错误！ eg；./mul_copy a.txt 512");
        exit(1);
    }

    int size = atoi(argv[2]);

    char buffer[1024 * size];

    memset(buffer, 0, sizeof(buffer));
    FILE *fp = fopen(argv[1], "r");
    if(!fp)
    {
        printf("打开文件错误！\n");
        exit(1);
    }
    FILE* fp1 = fopen("m.txt", "w");
    if(!fp1)
    {
        printf("失败！");
        exit(1);
    }
    unsigned char blockInfo[SHA256_DIGEST_LENGTH];
    unsigned char fileInfo[SHA256_DIGEST_LENGTH];
    
    //创建上下文
    EVP_MD_CTX* file_ctx = EVP_MD_CTX_new();
    //初始化算法
    EVP_DigestInit_ex(file_ctx, EVP_sha256(), NULL);

    while(size = fread(buffer, 1, sizeof(buffer), fp))
    {
        // 创建上下文用于当前块
        EVP_MD_CTX* blockCtx = EVP_MD_CTX_new();
        // 初始化算法
        EVP_DigestInit_ex(blockCtx, EVP_sha256(), NULL);
        //设置数据
        EVP_DigestUpdate(blockCtx, buffer, size);
        //获取摘要信息
        EVP_DigestFinal_ex(blockCtx, blockInfo, NULL);

        char block[SHA256_DIGEST_LENGTH*2+1];
        for(int i = 0; i < SHA256_DIGEST_LENGTH; i++)
        {
            snprintf(&block[i * 2], 3, "%02x", blockInfo[i]);
        }
        block[SHA256_DIGEST_LENGTH * 2] = '\0'; // 确保字符串以 null 结尾
        fwrite(block, 1, SHA256_DIGEST_LENGTH*2, fp1);
        fputc('\n', fp1);

        FILE* fp2 = fopen(block, "w");
        fwrite(buffer, 1, size, fp2);
        fclose(fp2);
        // 更新整个文件的上下文
        EVP_DigestUpdate(file_ctx, buffer, size);

        // 释放资源
        EVP_MD_CTX_free(blockCtx);
        // snprintf(buffer, sizeof(buffer), "%s\n", buffer);
    }
    //获取摘要信息
    EVP_DigestFinal_ex(file_ctx, fileInfo, NULL);
    //转化为16进制
    char file[SHA256_DIGEST_LENGTH*2+1];
    for(int i = 0; i < SHA256_DIGEST_LENGTH; i++)
    {
        snprintf(&file[i * 2], 3, "%02x", fileInfo[i]);
    }
    file[SHA256_DIGEST_LENGTH * 2] = '\0'; // 确保字符串以 null 结尾
    fwrite(file, 1, SHA256_DIGEST_LENGTH*2, fp1);
    EVP_MD_CTX_free(file_ctx);
    fclose(fp1);
    fclose(fp);
    return 0;
}